package lastRites.game.networking;

import java.util.logging.Level;
import java.util.logging.Logger;

import lastRites.entities.Player;
import lastRites.enums.CreatureType;
import lastRites.enums.GameStatus;
import lastRites.game.LastRites;
import lastRites.game.networking.NetworkPackets.ChatPacket;
import lastRites.game.networking.NetworkPackets.LoginRequest;
import lastRites.game.networking.NetworkPackets.LoginResponse;
import lastRites.game.networking.NetworkPackets.PlayerInfoPacket;
import lastRites.game.networking.NetworkPackets.PlayerListPacket;
import lastRites.game.networking.NetworkPackets.PlayerMovementRequest;
import lastRites.game.networking.NetworkPackets.PlayerMovementResponse;
import lastRites.game.networking.NetworkPackets.PlayerMovementUpdate;
import lastRites.game.networking.NetworkPackets.SignOff;
import lastRites.game.networking.NetworkPackets.TextDisplayPacket;

import com.esotericsoftware.kryonet.Connection;
import com.esotericsoftware.kryonet.Listener;
import com.esotericsoftware.kryonet.Server;

// ////////////////////////////////
// Listeners that the game uses //
// ////////////////////////////////
public class ServerListener extends Listener {
	Logger	logger	= Logger.getLogger( "ServerListener" );

	@Override
	public void received(Connection connection, Object object) {
		logger.setLevel( Level.OFF );
		if( object instanceof LoginRequest ) {
			logger.info( "Received login request" );
			LoginRequest login = (LoginRequest)object;
			// if already in, decline request
			// TODO: kick previous?
			if( LastRites.PLAYER_LIST.contains( login.accountName ) ) {
				connection.sendTCP( new LoginResponse( false ) );
				return;
			}
			// accept, add to active sessions, create playerinfo from account name
			PlayerInfoPacket info = new PlayerInfoPacket();
			// if we have a record, use that info, otherwise new account created
			if( LastRites.PLAYER_INFO.get( login.accountName ) != null ) {
				logger.info( "Login was a pre-existing player: " + login.accountName );
				info.player = LastRites.PLAYER_INFO.get( login.accountName );
				LastRites.PLAYER_LIST.add( info.player );
				connection.sendTCP( info );
			} else {
				logger.info( "Login was a new player: " + login.accountName );
				Player player = new Player();
				player.setName( login.accountName );
				player.setMovementSpeed( 75f );
				player.setCreatureType( CreatureType.GOLEM );
				info.player = player;
				LastRites.PLAYER_INFO.put( login.accountName, player );
				LastRites.PLAYER_LIST.add( player );
				connection.sendTCP( info );
			}
			// we're a server now if we weren't before
			// TODO: alter to accomodate real-time joining
			connection.sendTCP( new PlayerListPacket( LastRites.PLAYER_LIST ) );
			connection.sendTCP( new LoginResponse( true ) );
			LastRites.GAME_STATUS = GameStatus.SERVING;
			Network.sendMap();
		}
		// TODO: keep up to 100? allow client to change chat size
		if( object instanceof ChatPacket ) {
			logger.info( "Received a chat packet." );
			LastRites.CHAT_MESSAGES.add( ( (ChatPacket)object ).text );
			logger.info( "Sent ech of chat to all users." );
			if( connection.getEndPoint() instanceof Server ) {
				( (Server)connection.getEndPoint() ).sendToAllTCP( object );
			}
			if( LastRites.CHAT_MESSAGES.size() > 10 ) {
				LastRites.CHAT_MESSAGES.remove();
			}
		}
		if( object instanceof TextDisplayPacket ) {
			logger.info( "Received a text packet." );
			LastRites.TEXT_ON_SCREEN.add( (TextDisplayPacket)object );
		}
		if( object instanceof SignOff ) {
			logger.info( "Received a sign off packet." );
			LastRites.PLAYER_LIST.remove( ( (SignOff)object ).account );
			logger.info( "Closing connection" );
			connection.close();
		}
		if( object instanceof PlayerMovementRequest ) {
			PlayerMovementRequest packet = (PlayerMovementRequest)object;
			int x = (int)Math.floor( packet.x / LastRites.BLOCK_SIZE );
			int y = (int)Math.floor( packet.y / LastRites.BLOCK_SIZE );
			logger.info( "Received a player movement request packet for " + packet.player + " to move to " + "X:" + packet.x + " Y:" + packet.y );
			boolean passable = y < 0 || x < 0 || y > LastRites.CURRENT_WORLD.getBlocks().length || x > LastRites.CURRENT_WORLD.getBlocks()[0].length
					|| LastRites.CURRENT_WORLD.getBlocks()[y][x].getBlockType().isPassable();
			logger.info( "Position was passable: " + passable );
			if( passable ) {
				for( Player player : LastRites.PLAYER_LIST ) {
					if( player.getName().equalsIgnoreCase( packet.player ) ) {
						player.setPosition( packet.x, packet.y );
					}
				}
				connection.sendTCP( new PlayerMovementResponse( true ) );
				LastRites.SERVER.sendToAllExceptTCP( connection.getID(), new PlayerMovementUpdate( packet.player, packet.x, packet.y ) );
			} else {
				connection.sendTCP( new PlayerMovementResponse( false ) );
			}
		}
	}
}
